/**
 * Name: Avinash Sridhar	G Number: G00861300
 */
package udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;

import udp.Server.PhonebookEntry;

public class LookupService extends Thread {

	DatagramPacket mClientPacket;

	ArrayList<PhonebookEntry> mPhonebook;
	int mClientSocketPort;
	int mChildrenSocketPort;
	int mParentSocketPort;

	public LookupService(DatagramPacket packet, ArrayList<PhonebookEntry> phonebook, int clientSocketPort, int childrenSocketPort, int parentSocketPort) {

		mClientPacket = packet;

		mPhonebook = phonebook;

		mClientSocketPort = clientSocketPort;
		mChildrenSocketPort = childrenSocketPort;
		mParentSocketPort = parentSocketPort;
	}

	@Override
	public void run() {
		try {

			String findWord = new String(mClientPacket.getData(), 0, mClientPacket.getLength());

			if (findWord.equals("exit"))
			{
				mClientPacket = null;
				System.out.println("UDP server has received 'exit'status: UDP Client connection (only to the client that called 'exit') closed!");
			}
			else 
			{
				System.out.println("Got UDP client request to find value: " + findWord);

				//Sleep for 5 seconds
				sleep(5000);

				//look up value in your phonebook
				String lookup_result =  lookup(findWord);

				if (!lookup_result.equals(""))	//FOUND MATCH(ES)
				{
					System.out.println("found matches!");

					WriteToPort(lookup_result, mClientPacket.getPort());    				
				}
				else if (lookup_result.equals("")) //NOT FOUND
				{
					if (mParentSocketPort > 0)	//if you have a parent
					{
						//forward request to parent via parent_port 
						InetAddress server_addr = InetAddress.getByName("localhost");
						DatagramSocket fwd_client = new DatagramSocket(); //normally Integer.ParseInt(args[0])
						DatagramPacket fwd_packet = new DatagramPacket(findWord.getBytes(), findWord.length(), server_addr, mParentSocketPort);


						System.out.println("UDP Server (acting as client now) is FWDing a request to the UDP parent... at "+ mParentSocketPort);
						fwd_client.send(fwd_packet);

						//wait for result from the parent.......
						byte[] buffer = new byte[4096];
						DatagramPacket fwd_resultPacket = new DatagramPacket(buffer, buffer.length);
						fwd_client.receive(fwd_resultPacket);
						String fwd_result = new String(fwd_resultPacket.getData(), 0, fwd_resultPacket.getLength());

						System.out.println("UDP Server (acting as client now) has received from UDP parent : " + fwd_result);

						fwd_client.close();
						fwd_packet = null;

						WriteToPort(fwd_result, mClientPacket.getPort());
					}
					else if (mParentSocketPort == -1)	//if you are the root node
					{
						//send answer to client via client_port "NEVER-FOUND"	USE CASE: DONE.
						System.out.println("UDP Server is sending a result back to the UDP client...");
						WriteToPort("No Match.", mClientPacket.getPort());
					}
				}
			}		    	
			mClientPacket = null;
		} catch (IOException | InterruptedException e) {
			System.out.println("Interrupted socket connection...reset.");
			//e.printStackTrace();
		}
	}


	public void WriteToPort(String stringToWrite, int port)
	{
		try {
			System.out.println("UDP Server is replying to child " + mClientSocketPort);

			DatagramSocket client = new DatagramSocket(); //normally Integer.ParseInt(args[0])
			DatagramPacket packet = new DatagramPacket(stringToWrite.getBytes(), stringToWrite.length(), mClientPacket.getAddress(), port);					
			client.send(packet);
			client.close();
		} catch (IOException e) 
		{ e.printStackTrace(); }
	}

	public String lookup( String searchWord )
	{	
		System.out.println("looking up '" + searchWord + "' .....");

		String[] fullName = searchWord.split(" ");
		String result = "";
		boolean firstNameMatch;
		boolean lastNameMatch;

		//look for the entry		
		for (PhonebookEntry temp : mPhonebook) 
		{
			if (temp.mFirstName != null && temp.mLastName != null)
			{
				firstNameMatch = ( temp.mFirstName.equalsIgnoreCase(fullName[0]) || fullName[0].equalsIgnoreCase("*") );
				lastNameMatch = ( temp.mLastName.equalsIgnoreCase(fullName[1]) || fullName[1].equalsIgnoreCase("*") );
				if (firstNameMatch && lastNameMatch)
				{
					result += temp.mFirstName + " " + temp.mLastName + " " + temp.mPhoneNumber + "%";
				}
			}
		}
		return result;
	}

}
